import numpy

from . import irt
from .simulation import Stopper


class MaxItemMinErrorStopper(Stopper):
    """达到最小标准误差或者达到最大试题数量停止"""

    def __str__(self):
        return 'Min Error Or Max Items Initializer'

    def __init__(self, min_error=0.2, max_item_num=100):
        """
        构造函数
        :param min_error: 最新标准误差
        :param _max_item_num: 最多试题数量
        """
        super().__init__()
        self._min_error = min_error
        self._max_item_num = max_item_num

    def stop(
            self,
            index: int = None,
            administered_items: numpy.ndarray = None,
            theta: float = None,
            **kwargs
    ) -> bool:
        """Checks whether the test reached its stopping criterion

        :param index: the index of the current examinee
        :param administered_items: a matrix containing the parameters of items that were already administered
        :param theta: a float containing the a proficiency value to which the error will be calculated
        :returns: `True` if the test met its stopping criterion, else `False`"""

        if (index is None or
            self.simulator is None) and (administered_items is None or theta is None):
            raise ValueError

        if administered_items is None and theta is None:
            theta = self.simulator.latest_estimations[index]
            administered_items = self.simulator.items[self.simulator.administered_items[index]]

        if theta is None:
            return False

        if administered_items.shape[0] == self._max_item_num:
            return True

        return irt.see(theta, administered_items) < self._min_error
